package guru.merlin.bus;

import guru.merlin.core.Envelope;
import guru.merlin.core.EnvelopeHandler;

import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueReceiver;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.Session;

import org.apache.log4j.Logger;

/**
 * Actualmente solo soporta mensajes de texto.
 *
 * @author Cesar Obach-Renner, cesar@guru.com.ve
 * @version 1.0
 */

class JMSQueue implements UVQueue, MessageListener{
    static Logger logger = Logger.getLogger (JMSQueue.class);
    
    String queueName = null;
    QueueConnectionFactory queueConnectionFactory = null;
    public QueueConnection queueConnection = null;
    QueueSession queueSession = null;
    Queue queue = null;
    
    QueueSender queueSender = null;
    QueueReceiver queueReceiver = null;
    
    ObjectMessage message = null;
    //int exitResult = 0;
    
    static int nextId = 1;
    public int id;
    EnvelopeHandler handler;
    
    private void conectionSetup (String qName) throws Exception {
        try {
            this.queueName = qName;
            queueConnectionFactory = new com.sun.messaging.QueueConnectionFactory ();
            //getQueueConnectionFactory();
            logger.info ("queueName to be created: "+qName);
            queueConnection = queueConnectionFactory.createQueueConnection ();            
            queueSession = queueConnection.createQueueSession (false, Session.AUTO_ACKNOWLEDGE);           
            queue = new com.sun.messaging.Queue (queueName);
            
            //getQueue(queueName, queueSession);
        } catch (Throwable t) {
            t.printStackTrace ();
            throw new Exception(t);
        }
        
    }
    
    /**
     * Instanciacion como Proveedor
     *
     */
    public JMSQueue (String qName) throws Exception {
        id = nextId++;
        //OJO: Verificar que qName no sea null o vacio
        conectionSetup (qName);
        queueSender = queueSession.createSender (queue);
        logger.info ("JMSQueue #" + id + " created!(qname=" + qName + ")");
        
    }
    
    /**
     * Instanciacion como Consumidor
     *
     */
    public JMSQueue (String qName, EnvelopeHandler handler) throws Exception {
        id = nextId++;
        this.handler = handler;
        
        //OJO: Verificar que qName no sea null o vacio
        conectionSetup (qName);
        queueReceiver = queueSession.createReceiver (queue);
        queueReceiver.setMessageListener (this);
        logger.info ("JMSQueue #" + id + " created!(qname=" + qName + ")");
        
    }
    
    public void start () throws Exception {
        queueConnection.start ();
    }
    
    public void stop () throws Exception {
        queueConnection.stop ();
    }
    
    public void onMessage (Message message) {
        try {
            if (message instanceof ObjectMessage) {
                ObjectMessage msg = (ObjectMessage) message;
                Envelope envelope = (Envelope) msg.getObject ();
                handler.handEnvelope (envelope); //Le pasa el envelope al handler (EPContainer)
            } else {
                throw new InternalError ("onMessage(1)@JMSQueue: message was not an instance of ObjectMessage");
            }
        } catch (Throwable t) {
            t.printStackTrace ();
            throw new InternalError ("onMessage(2)@JMSQueue:" + t);
            
        } finally{
            
        }
    }
    
    public void finalize () throws Exception {
        try {
            if (queueConnection != null) {
                queueConnection.close ();
                logger.info ("===>JMSQueue #" + id + " conecction closed!");
            }
        }  finally {
        }
    }
    
    public void send (Envelope envelope) throws Exception {
        try {
            String msg = "";
            message = queueSession.createObjectMessage ();
            message.setObject (envelope);
            if (logger.isDebugEnabled ()) {
                msg = "[send@JMSQueue] Sending message: " + envelope.toString ();
                logger.debug (msg);
            }
            queueSender.send (message);
        }  finally{
            
        }
    }
    
    public static javax.jms.QueueConnectionFactory getQueueConnectionFactory () throws Exception {
        //return new com.sun.messaging.QueueConnectionFactory();
        return (null);
    }
    
    public static javax.jms.Queue getQueue (String name, javax.jms.QueueSession session) throws Exception {
        //return session.createQueue(name);
        return (null);
    }
    
    public QueueConnection getQueueConnection () throws Exception {
        return this.queueConnection;
    }
}